#include "Track.h"
#include "Jet.h"
#include "Player.h"
#include "Interpolation.h"

extern DebugTracer _DEBUGTRACER;
Track::Track()
{
    m_playerList = NULL;
}
Track::~Track()
{
    //dtor
}
void Track::SetPlayerList(std::vector<Player*>* player_list, unsigned int player_placement)
{
    m_playerList = player_list;
    std::vector<Player*>::iterator it;
    for(it = player_list->begin(); it < player_list->end(); it++)
    {
        Jet* jet = (*it)->GetJet();
        jet->SetTrack(this);
        (*it)->ChooseTrack(this);
        m_jetList.push_back(jet);
    }

    //initialising the jet positions depending on the player placement
    //
    //-TO-DO : placing the jets in some order (random? tournament?)
    //

    /*float distance_counter = m_vectorList.size() - 1;
    switch(player_placement)
    {
        case ONELINE:
        {
            for(it = player_list->begin(); it < player_list->end(); it++)
            {
                (*it)->GetJet()->SetPosition(m_vectorList[distance_counter].Position);
                distance_counter -= (JET_SIZEZ/2 + JET_PLACEMENT_DISTANCE);
            }
        }
        break;
        case TWOLINES:
        {
            for(it = player_list->begin(); it < player_list->end(); it++)
            {
                _DEBUGTRACER.Print("initialising positions...");
                _DEBUGTRACER.Print(distance_counter);

                (*it)->GetJet()->SetPosition(m_vectorList[distance_counter].Position);
                distance_counter -= (JET_SIZEZ/2 + JET_PLACEMENT_DISTANCE);

                _DEBUGTRACER.Print("positions initialised");
            }
        }
        break;
    }
    */

}
void Track::AddTrackNode(Ogre::Vector3 position,
                               Ogre::Vector3 normal,
                               std::string material,
                               Ogre::Real size,
                               bool end)
{
    TrackNode node;
    node.Position = position;
    node.Normal = normal;
    node.Size = size;
    node.Texture = material;

    m_trackNodeList.push_back(node);
    if(m_trackNodeList.size() > 3)
        buildTrack();
}
void Track::buildTrack()
{

    TrackNode* first_node = NULL;
    TrackNode* third_node = NULL;
    TrackNode* fourth_node = NULL;

    static TrackVector vector;
    static Ogre::Vector3 distance;
    static std::vector<TrackNode>::iterator it;
    m_vectorList.clear();

    int vector_counter = 0;

    for(unsigned int index = 0; index < m_trackNodeList.size(); index++)
    {
        if(index + 1 >= m_trackNodeList.size())
            m_trackNodeList[index].Director = m_trackNodeList[0].Position - m_trackNodeList[index].Position;
        else
            m_trackNodeList[index].Director = m_trackNodeList[index+1].Position - m_trackNodeList[index].Position;

        m_trackNodeList[index].Curvature = m_trackNodeList[index].Director.crossProduct(m_trackNodeList[index].Normal);
        m_trackNodeList[index].Curvature.normalise();
        m_trackNodeList[index].Curvature *= m_trackNodeList[index].Size;
    }

    for(unsigned int index = 0; index < m_trackNodeList.size(); index++)
    {
        if(&m_trackNodeList[index] == &m_trackNodeList.back())
        {
            third_node = &m_trackNodeList.front();
            fourth_node = &m_trackNodeList[1];
            first_node = &m_trackNodeList[index-1];
        }
        else if(&m_trackNodeList[index] == &m_trackNodeList.front())
        {
            first_node = &m_trackNodeList.back();
            third_node = &m_trackNodeList[1];
            fourth_node = &m_trackNodeList[2];
        }
        else if(&m_trackNodeList[index + 1] == &m_trackNodeList.back())
        {
            third_node = &m_trackNodeList.back();
            fourth_node = &m_trackNodeList.front();
            first_node = &(m_trackNodeList[index - 1]);
        }
        else
        {
            first_node = &m_trackNodeList[index-1];
            third_node = &m_trackNodeList[index+1];
            fourth_node = &m_trackNodeList[index+2];
        }

        distance = third_node->Position - m_trackNodeList[index].Position;

        for(float i = 0; i < 1; i += METERS_PER_NODE/distance.length())
        {
            vector.SetX(Interpolation::CubicInterpolate(first_node->Position.x,
                                                                m_trackNodeList[index].Position.x,
                                                                third_node->Position.x,
                                                                fourth_node->Position.x,
                                                                i));

            vector.SetY(Interpolation::CubicInterpolate(first_node->Position.y,
                                                                m_trackNodeList[index].Position.y,
                                                                third_node->Position.y,
                                                                fourth_node->Position.y,
                                                                i));

            vector.SetZ(Interpolation::CubicInterpolate(first_node->Position.z,
                                                                m_trackNodeList[index].Position.z,
                                                                third_node->Position.z,
                                                                fourth_node->Position.z,
                                                                i));

            vector.SetCurvatureX(Interpolation::CubicInterpolate(first_node->Curvature.x,
                                                                m_trackNodeList[index].Curvature.x,
                                                                third_node->Curvature.x,
                                                                fourth_node->Curvature.x,
                                                                i));

            vector.SetCurvatureY(Interpolation::CubicInterpolate(first_node->Curvature.y,
                                                                m_trackNodeList[index].Curvature.y,
                                                                third_node->Curvature.y,
                                                                fourth_node->Curvature.y,
                                                                i));

            vector.SetCurvatureZ(Interpolation::CubicInterpolate(first_node->Curvature.z,
                                                                m_trackNodeList[index].Curvature.z,
                                                                third_node->Curvature.z,
                                                                fourth_node->Curvature.z,
                                                                i));

            m_vectorList.push_back(vector);
            vector_counter++;
        }

    }
    std::vector<TrackVector>::iterator vecIt;
    TrackVector* next_vector;

    for(vecIt = m_vectorList.begin(); vecIt < m_vectorList.end(); vecIt++)
    {
        if(&(*vecIt) == &m_vectorList.back())
            next_vector = &m_vectorList.front();
        else
            next_vector = &(*(vecIt+1));

        (*vecIt).SetDirector(next_vector->GetPosition() - (*vecIt).GetPosition());
        (*vecIt).SetCurvature((*vecIt).GetCurvature().normalisedCopy());
        (*vecIt).SetSize(10);
        (*vecIt).SetCurvature((*vecIt).GetCurvature() *= (*vecIt).GetSize());
        (*vecIt).SetNormal((*vecIt).GetDirector().crossProduct((*vecIt).GetCurvature()));
        (*vecIt).SetNormal((*vecIt).GetNormal().normalisedCopy());
    }


}

void Track::Update(float timedelta)
{
}
